package com.itao;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.AbstractListener;
import jakarta.annotation.Resource;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationEventPublisher;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
public class GatewayApplication implements CommandLineRunner {

    @Resource
    private InMemoryRouteDefinitionRepository routeDefinitionWriter;
    @Resource
    private ApplicationEventPublisher publisher;
    @Resource
    private NacosConfigManager nacosConfigManager;
    private final Map<String, RouteDefinition> routeMap = new HashMap<>();

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        var configService = nacosConfigManager.getConfigService();
        String config = configService.getConfigAndSignListener(
                "gateway-route",
                "DEFAULT_GROUP",
                3000,
                new AbstractListener() {
                    @Override
                    public void receiveConfigInfo(String configInfo) {
                        publishe(configInfo);
                    }
                });
        publishe(config);
    }

    private void publishe(String config) {
        var routeDefinitions = JSONUtil.toList(config, RouteDefinition.class);
        routeMap.keySet().forEach(routeId -> routeDefinitionWriter.delete(Mono.just(routeId)).subscribe());
        if (CollUtil.isNotEmpty(routeDefinitions)) {
            routeDefinitions.forEach(route -> {
                routeMap.put(route.getId(), route);
                routeDefinitionWriter.save(Mono.just(route)).subscribe();
            });
        }
        publisher.publishEvent(new RefreshRoutesEvent(config));
    }
}